package com.jyw.business.de.service.impl;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.jyw.business.de.constant.DemandStateConstant;
import com.jyw.business.de.constant.TaskProcessConstant;
import com.jyw.business.de.constant.TaskStateConstant;
import com.jyw.business.de.constant.TaskTypeConstant;
import com.jyw.business.de.domain.DeDemandInfo;
import com.jyw.business.de.domain.DeTaskProcess;
import com.jyw.business.de.domain.dto.web.*;
import com.jyw.business.de.domain.vo.web.TaskDetailVO;
import com.jyw.business.de.domain.vo.web.TaskPageVO;
import com.jyw.business.de.domain.vo.web.TaskProcessVO;
import com.jyw.business.de.service.IDeDemandInfoService;
import com.jyw.business.de.service.IDeTaskProcessService;
import com.jyw.common.core.domain.model.SimpleDto;
import com.jyw.common.exception.ServiceException;
import com.jyw.common.utils.DateUtils;
import com.jyw.common.utils.SecurityUtils;
import com.jyw.system.utils.ConversionUtil;
import com.jyw.system.utils.FileUtils;
import org.springframework.stereotype.Service;
import com.jyw.business.de.mapper.DeTaskInfoMapper;
import com.jyw.business.de.domain.DeTaskInfo;
import com.jyw.business.de.service.IDeTaskInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;

/**
 * 需求-任务Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-02-19
 */
@Service
public class DeTaskInfoServiceImpl extends ServiceImpl<DeTaskInfoMapper,DeTaskInfo> implements IDeTaskInfoService
{
    @Resource
    private DeTaskInfoMapper deTaskInfoMapper;

    @Resource
    private IDeDemandInfoService deDemandInfoService;

    @Resource
    private IDeTaskProcessService processService;

    /**
     * 查询需求-任务
     * 
     * @param id 需求-任务主键
     * @return 需求-任务
     */
    @Override
    public DeTaskInfo selectDeTaskInfoById(Long id)
    {
        return deTaskInfoMapper.selectDeTaskInfoById(id);
    }

    /**
     * 查询需求-任务列表
     * 
     * @param deTaskInfo 需求-任务
     * @return 需求-任务
     */
    @Override
    public List<DeTaskInfo> selectDeTaskInfoList(DeTaskInfo deTaskInfo)
    {
        return deTaskInfoMapper.selectDeTaskInfoList(deTaskInfo);
    }

    /**
     * 新增需求-任务
     * 
     * @param deTaskInfo 需求-任务
     * @return 结果
     */
    @Override
    public int insertDeTaskInfo(DeTaskInfo deTaskInfo)
    {
        deTaskInfo.setCreateTime(DateUtils.getNowDate());
        return deTaskInfoMapper.insertDeTaskInfo(deTaskInfo);
    }

    /**
     * 修改需求-任务
     * 
     * @param deTaskInfo 需求-任务
     * @return 结果
     */
    @Override
    public int updateDeTaskInfo(DeTaskInfo deTaskInfo)
    {
        deTaskInfo.setUpdateTime(DateUtils.getNowDate());
        return deTaskInfoMapper.updateDeTaskInfo(deTaskInfo);
    }

    /**
     * 批量删除需求-任务
     * 
     * @param ids 需要删除的需求-任务主键
     * @return 结果
     */
    @Override
    public int deleteDeTaskInfoByIds(Long[] ids)
    {
        return deTaskInfoMapper.deleteDeTaskInfoByIds(ids);
    }

    /**
     * 删除需求-任务信息
     * 
     * @param id 需求-任务主键
     * @return 结果
     */
    @Override
    public int deleteDeTaskInfoById(Long id)
    {
        return deTaskInfoMapper.deleteDeTaskInfoById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void demandAddTask(TaskAddDto dto) {
        dto.setTaskType(TaskTypeConstant.DEMAND);
        DeDemandInfo info = deDemandInfoService.getById(dto.getDemandId());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!Arrays.asList(DemandStateConstant.RESEARCH,DemandStateConstant.ANALYZE,DemandStateConstant.RATING,DemandStateConstant.PROCESSING).contains(info.getDemandState())){
            throw new ServiceException("当前需求状态不能创建任务");
        }

        DeTaskInfo task = dto.buildTask();
        //写入任务
        save(task);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void demandPause(DemandOperDto dto) {
        //查询该需求下的所有任务(处理中与待接收)
        List<DeTaskInfo> list = lambdaQuery()
                .eq(DeTaskInfo::getTaskType, TaskTypeConstant.DEMAND)
                .eq(DeTaskInfo::getDemandId, dto.getId())
                .in(DeTaskInfo::getTaskState, Arrays.asList(TaskStateConstant.WAIT_ACCEPT, TaskStateConstant.PROCESSING))
                .list();
        //开始暂停任务
        list.forEach(data->{
            lambdaUpdate()
                    .eq(DeTaskInfo::getId,data.getId())
                    .set(DeTaskInfo::getTaskState,TaskStateConstant.PAUSE)
                    .set(DeTaskInfo::getPauseState,data.getTaskState())
                    .update();
            //记录流程
            processService.saveProcess(data.getId(), TaskProcessConstant.PAUSE,dto);
        });

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void demandTermination(DemandOperDto dto) {
//查询该需求下的所有任务(处理中与待接收暂停)
        List<DeTaskInfo> list = lambdaQuery()
                .eq(DeTaskInfo::getTaskType, TaskTypeConstant.DEMAND)
                .eq(DeTaskInfo::getDemandId, dto.getId())
                .in(DeTaskInfo::getTaskState, Arrays.asList(TaskStateConstant.WAIT_ACCEPT, TaskStateConstant.PROCESSING,TaskStateConstant.PAUSE))
                .list();
        //开始暂停任务
        list.forEach(data->{
            lambdaUpdate()
                    .eq(DeTaskInfo::getId,data.getId())
                    .set(DeTaskInfo::getTaskState,TaskStateConstant.TERMINATION)
                    .update();
            //记录流程
            processService.saveProcess(data.getId(), TaskProcessConstant.TERMINATION,dto);
        });
    }

    @Override
    public List<TaskPageVO> taskPage(TaskPageDto dto) {
        if(!SecurityUtils.isAdmin()){
            dto.setCurrentUser(SecurityUtils.getUserId());
        }
        List<TaskPageVO> list = deTaskInfoMapper.taskPage(dto);
        return ConversionUtil.conversionList(list,TaskPageVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void accept(SimpleDto<Long> dto) {
        DeTaskInfo taskInfo = getById(dto.getData());
        if(ObjectUtils.isEmpty(taskInfo)){
            throw new ServiceException("任务不存在");
        }
        if(!TaskStateConstant.WAIT_ACCEPT.equals(taskInfo.getTaskState())){
            throw new ServiceException("任务不为待接收,无法接收");
        }
        //修改状态
        lambdaUpdate()
                .eq(DeTaskInfo::getId,dto.getData())
                .set(DeTaskInfo::getTaskUser,SecurityUtils.getUserId())
                .set(DeTaskInfo::getTaskState,TaskStateConstant.PROCESSING)
                .set(DeTaskInfo::getUpdateTime,DateUtils.getNowDate())
                .update();
        //记录接收流程
        processService.saveProcess(dto.getData(),TaskProcessConstant.ACCEPT,null);
    }

    @Override
    public void back(DemandOperDto dto) {
        DeTaskInfo taskInfo = getById(dto.getId());
        if(ObjectUtils.isEmpty(taskInfo)){
            throw new ServiceException("任务不存在");
        }
        if(!TaskStateConstant.WAIT_ACCEPT.equals(taskInfo.getTaskState())){
            throw new ServiceException("任务不为待接收,无法退回");
        }
        //修改状态
        lambdaUpdate()
                .eq(DeTaskInfo::getId,dto.getId())
                .set(DeTaskInfo::getTaskUser,null)
                .set(DeTaskInfo::getTaskState,TaskStateConstant.WAIT_ALLOCATION)
                .set(DeTaskInfo::getUpdateTime,DateUtils.getNowDate())
                .update();
        //记录退回流程
        processService.saveProcess(dto.getId(),TaskProcessConstant.BACK,dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void make(TaskMakeDto dto) {
        DeTaskInfo taskInfo = getById(dto.getId());
        if(ObjectUtils.isEmpty(taskInfo)){
            throw new ServiceException("任务不存在");
        }
        if(!TaskStateConstant.WAIT_ACCEPT.equals(taskInfo.getTaskState())){
            throw new ServiceException("任务不为待接收,无法退回");
        }
        DeTaskInfo updateTask = dto.buildTask();
        updateById(updateTask);
        //记录处理流程
        processService.saveProcess(dto.getId(),TaskProcessConstant.COMPLETED,dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pause(DemandOperDto dto) {
        DeTaskInfo taskInfo = getById(dto.getId());
        if(ObjectUtils.isEmpty(taskInfo)){
            throw new ServiceException("任务不存在");
        }
        if(!Arrays.asList(TaskStateConstant.WAIT_ALLOCATION,TaskStateConstant.WAIT_ACCEPT,TaskStateConstant.PROCESSING).contains(taskInfo.getTaskState())){
            throw new ServiceException("当前任务状态不能暂停");
        }
        //修改状态
        lambdaUpdate()
                .eq(DeTaskInfo::getId,dto.getId())
                .set(DeTaskInfo::getTaskState,TaskStateConstant.PAUSE)
                .set(DeTaskInfo::getPauseState, taskInfo.getTaskState())
                .set(DeTaskInfo::getUpdateTime,DateUtils.getNowDate())
                .update();
        //记录处理流程
        processService.saveProcess(dto.getId(),TaskProcessConstant.PAUSE,dto);
    }

    @Override
    public void termination(DemandOperDto dto) {
        DeTaskInfo taskInfo = getById(dto.getId());
        if(ObjectUtils.isEmpty(taskInfo)){
            throw new ServiceException("任务不存在");
        }
        if(!Arrays.asList(TaskStateConstant.WAIT_ALLOCATION,TaskStateConstant.WAIT_ACCEPT,TaskStateConstant.PROCESSING,TaskStateConstant.PAUSE).contains(taskInfo.getTaskState())){
            throw new ServiceException("当前任务状态不能终止");
        }
        //修改状态
        lambdaUpdate()
                .eq(DeTaskInfo::getId,dto.getId())
                .set(DeTaskInfo::getTaskState,TaskStateConstant.TERMINATION)
                .set(DeTaskInfo::getUpdateTime,DateUtils.getNowDate())
                .update();
        //记录处理流程
        processService.saveProcess(dto.getId(),TaskProcessConstant.TERMINATION,dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void open(SimpleDto<Long> dto) {
        DeTaskInfo taskInfo = getById(dto.getData());
        if(ObjectUtils.isEmpty(taskInfo)){
            throw new ServiceException("任务不存在");
        }
        if(!TaskStateConstant.PAUSE.equals(taskInfo.getTaskState())){
            throw new ServiceException("当前任务状态不能开启");
        }
        //判断需求是否为暂停
        if(taskInfo.getTaskType().equals(TaskTypeConstant.DEMAND)){
            DeDemandInfo demandInfo = deDemandInfoService.getById(taskInfo.getDemandId());
            if(demandInfo.getDemandState().equals(DemandStateConstant.PAUSE)){
                throw new ServiceException("该任务的需求已暂停，无法开启任务，请先开启需求后再来开启任务");
            }
        }
        //修改状态
        lambdaUpdate()
                .eq(DeTaskInfo::getId,dto.getData())
                .set(DeTaskInfo::getTaskState,taskInfo.getPauseState())
                .set(DeTaskInfo::getPauseState,null)
                .set(DeTaskInfo::getUpdateTime,DateUtils.getNowDate())
                .update();
        //记录处理流程
        processService.saveProcess(dto.getData(),TaskProcessConstant.OPEN,null);
    }

    @Override
    public void hurry(SimpleDto<Long> dto) {
        DeTaskInfo taskInfo = getById(dto.getData());
        if(ObjectUtils.isEmpty(taskInfo)){
            throw new ServiceException("任务不存在");
        }
        //修改状态
        lambdaUpdate()
                .eq(DeTaskInfo::getId,dto.getData())
                .set(DeTaskInfo::getTaskHurry,taskInfo.getTaskHurry()+1)
                .update();
        //记录处理流程
        processService.saveProcess(dto.getData(),TaskProcessConstant.HURRY,taskInfo.getTaskHurry()+1);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void demandEditTask(TaskEditDto dto) {
        DeTaskInfo taskInfo = getById(dto.getId());
        if(ObjectUtils.isEmpty(taskInfo)){
            throw new ServiceException("任务不存在");
        }
        DeTaskInfo task = dto.buildTask();
        if(taskInfo.getTaskState().equals(TaskStateConstant.WAIT_ALLOCATION)){
            task.setTaskState(TaskStateConstant.WAIT_ACCEPT);
            task.setWaitAcceptTime(DateUtils.getNowDate());
        }
        updateById(task);
    }

    @Override
    public TaskDetailVO getInfo(Long id) {
        TaskDetailVO detail = deTaskInfoMapper.getInfo(id);
        detail.setTaskEnclosureList(FileUtils.IdToFile(detail.getTaskEnclosure()));
        return ConversionUtil.conversion(detail,TaskDetailVO.class);
    }

    @Override
    public List<TaskProcessVO> getProcessInfo(Long id) {
        List<DeTaskProcess> list = processService.lambdaQuery()
                .eq(DeTaskProcess::getTaskId, id)
                .orderByDesc(DeTaskProcess::getId)
                .list();
        return list.stream().map(data -> ConversionUtil.conversion(new TaskProcessVO(data), TaskProcessVO.class)).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderAddTask(TaskAddDto dto) {
        dto.setTaskType(TaskTypeConstant.ORDER);
        DeTaskInfo task = dto.buildTask();
        //写入任务
        save(task);
    }

    @Override
    public Boolean taskOverInfo(Long demandId) {
        //检查当前需求下是否还有任务未完成
        Integer count = lambdaQuery()
                .eq(DeTaskInfo::getDemandId, demandId)
                .in(DeTaskInfo::getTaskState, Arrays.asList(TaskStateConstant.WAIT_ACCEPT, TaskStateConstant.PROCESSING, TaskStateConstant.PAUSE))
                .count();
        return count==0;
    }
}
